package com.example.rpapp.activity.command;

import cn.hutool.core.collection.CollectionUtil;
import com.example.rpapp.assembler.AwardAssembler;
import com.example.rpapp.context.ActivityDrawContext;
import com.example.rpclient.dto.data.ActivityConfigVo;
import com.example.rpclient.dto.data.ActivityVo;
import com.example.rpclient.dto.data.AwardVo;
import com.example.rpclient.dto.data.DrawResultVo;
import com.example.rpdomain.award.AwardEntity;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

 
@Slf4j
public abstract class BaseDrawExe {


    /**
     * 抽奖模板方法，流程不会改动
     *
     * @param context
     * @return
     */
    public final DrawResultVo execute(ActivityDrawContext context) {
        // 校验活动时间
        checkActivityTime(context.getActivityConfigVo().getActivityVo());
        // 校验活动规则
        checkActivityRule(context.getActivityConfigVo());
        // 剔除奖项库存为空的项
        List<AwardVo> awardVoList = removeAwardInventoryNull(context.getActivityConfigVo().getAwardVoList());
        // 调用抽奖算法进行抽奖
        context.setAwardVo(getAward(awardVoList));

        context.setAwardEntity(AwardAssembler.toAwardEntity(context.getAwardVo()));
        context.setIsWinTheLottery(context.getAwardEntity().isPrize());
        if (Boolean.FALSE.equals(context.getIsWinTheLottery())) {
            // 插入未中奖记录
            return addRecordAndGetDrawResultVo(context);
        }

        Boolean drawBefore = Boolean.TRUE;
        try {
            // 调用抽奖后续流程，流程内容自定义
            drawBefore = drawBefore(context);
        } catch (Exception e) {
            //错误处理
            drawBefore = Boolean.FALSE;
            log.error("执行drawBefore方法出错，默认返回未中奖信息，", e);
        }

        if (Boolean.FALSE.equals(drawBefore)) {
            // 执行 drawBefore 出错，默认返回未中奖
            context.setAwardVo(getNotAward(context.getActivityConfigVo().getAwardVoList()));
            context.setAwardEntity(AwardAssembler.toAwardEntity(context.getAwardVo()));
            context.setIsWinTheLottery(Boolean.FALSE);
            return addRecordAndGetDrawResultVo(context);
        }

        // 返回结果
        return getDrawResultVo(context.getAwardEntity());
    }

    protected abstract DrawResultVo addRecordAndGetDrawResultVo(ActivityDrawContext context);

    protected abstract Boolean drawBefore(ActivityDrawContext context);

    protected abstract void addRecord(ActivityDrawContext context);

    protected abstract DrawResultVo getDrawResultVo(AwardEntity awardEntity);

    protected abstract AwardVo getAward(List<AwardVo> awardVoList);

    protected abstract void checkActivityRule(ActivityConfigVo activityConfigVo);

    /**
     * 校验活动
     *
     * @param activityVo
     */
    protected abstract void checkActivityTime(ActivityVo activityVo);



    private AwardVo getNotAward(List<AwardVo> awardVoList) {
        for (AwardVo awardVo : awardVoList) {
            if ("0".equals(awardVo.getPrizeId().toString())) {
                return awardVo;
            }
        }
        return null;
    }

    private DrawResultVo getDefaultDrawResultVo(List<AwardVo> awardVoList) {
        return getDrawResultVo(AwardAssembler.toAwardEntity(getNotAward(awardVoList)));
    }

    private  List<AwardVo> removeAwardInventoryNull(List<AwardVo> awardVoList){
        if (CollectionUtil.isEmpty(awardVoList)) {
            return new ArrayList<>();
        }
        return awardVoList.stream()
                .filter(item -> item.getNumber() > 0 || "0".equals(item.getPrizeId().toString()))
                .collect(Collectors.toList());
    }

}